﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using Kugar.Core.ExtMethod;
using Kugar.Core.Printer;
namespace Kugar.UI.WinForm
{
    [Editor("System.Windows.Forms.Design.DataGridViewComponentEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(ComponentEditor))]
    [Designer("System.Windows.Forms.Design.DataGridViewDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    public class DataGridViewEx : DataGridView
    {
        DataGridViewCheckBoxColumn _selectColumn = null;
        private HashSet<DataGridViewRow> _checkedList = new HashSet<DataGridViewRow>();
        private int _rowHeight = 0;

        public DataGridViewEx()
            : base()
        {
            _rowHeight = ColumnHeadersHeight;

            //base.FirstDisplayedScrollingRowIndex
            base.Scroll += Scrolling;

            _selectColumn = new DataGridViewCheckBoxColumn(false);
            _selectColumn.Name = "_selectColumn";
            _selectColumn.ValueType = typeof(bool);
            _selectColumn.Width = 20;
            _selectColumn.Resizable = DataGridViewTriState.False;
            _selectColumn.HeaderText = "";

            IsRedWhenNegativeNumber = false;
            IsLoadFinish = false;

            base.AutoGenerateColumns = false;

            OnMultiSelectChanged(EventArgs.Empty);

            this.CellMouseDoubleClick += this.DataGridViewEx_CellMouseDoubleClick;
            this.CellPainting += this.DataGridViewEx_CellPainting;
        }

        public DataGridViewCell this[int rowIndex,int cellIndex]
        {
            get { return this.Rows[rowIndex].Cells[cellIndex]; }
        }

        public DataGridViewCell this[int rowIndex,string colName]
        {
            get { return this.Rows[rowIndex].Cells[colName]; }
        }

        private bool _isShowSelectColumn;
        public bool ShowSelectColumn
        {
            get { return _isShowSelectColumn; }
            set
            {
                _isShowSelectColumn = value;
                OnMultiSelectChanged(EventArgs.Empty);
            }
        }

        [Browsable(false)]
        public DataGridViewRow[] CheckedRows
        {
            get
            {
                return _checkedList.OrderBy(x => x.Index).ToArray();
            }
        }

        private void Scrolling(object sender, ScrollEventArgs e)
        {
            if (IsLoadFinish)
            {
                return;
            }

            if (e.ScrollOrientation == ScrollOrientation.VerticalScroll )//&& e.NewValue >= base.Rows.Count * 0.3)
            {
                var dataGrid = (DataGridView) sender;

                if (dataGrid.FirstDisplayedScrollingRowIndex > dataGrid.Rows.Count * 0.6)
                {
                    if (DataNeed != null)
                    {
                        DataNeed(this, EventArgs.Empty);
                    }
                }
            }
        }

        /// <summary>
        ///     获取或设置当前数据源是否已加载完成
        /// </summary>
        [Browsable(false)]
        public bool IsLoadFinish { set; get; }

        /// <summary>
        ///     当单元格为负数时，是否显示红色字体
        /// </summary>
        public bool IsRedWhenNegativeNumber { set; get; }

        /// <summary>
        /// 当滚动加载需要数据时，引发该事件
        /// </summary>
        public event EventHandler DataNeed;

        private void DataGridViewEx_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (IsRedWhenNegativeNumber)
            {
                object value = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
                bool isRed = false;


                if (value is int && (int)value < 0) isRed = true;
                else if (value is decimal && (decimal)value <= 0) isRed = true;
                else if (value is float && (float)value <= 0) isRed = true;
                else if (value is double && (double)value <= 0) isRed = true;

                if (isRed)
                {
                    this.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.ForeColor = Color.Red;
                }
            }
        }

        private void DataGridViewEx_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (!this.Columns.Contains("_selectColumn"))
                {
                    return;
                }

                var v = (bool?)base.Rows[e.RowIndex].Cells["_selectColumn"].Value;

                if (MultiSelect)
                {
                    base.Rows[e.RowIndex].Cells["_selectColumn"].Value = !v.GetValueOrDefault();
                }

                base.Rows[e.RowIndex].Selected = !base.Rows[e.RowIndex].Selected;
            }

        }

        protected override void OnMultiSelectChanged(EventArgs e)
        {
            if (MultiSelect)
            {
                if (ShowSelectColumn)
                {
                    if (!base.Columns.Contains("_selectColumn"))
                    {
                        base.Columns.Insert(0, _selectColumn);
                        foreach (DataGridViewRow row in base.SelectedRows)
                        {
                            row.Cells["_selectColumn"].Value = true;
                        }
                    }

                    _selectColumn.Visible = true;
                }
            }
            else
            {
                _selectColumn.Visible = false;
            }

            base.OnMultiSelectChanged(e);
        }

        protected override void OnCellValueChanged(DataGridViewCellEventArgs e)
        {
            var column = base.Columns[e.ColumnIndex];

            if (column.Name == "_selectColumn")
            {
                var value = (bool?)base.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
                var currentRow = base.Rows[e.RowIndex];
                if (value == true && _checkedList.Contains(currentRow))
                {
                    _checkedList.Add(currentRow);
                }

                if (!MultiSelect && value == true)
                {
                    foreach (DataGridViewRow row in _checkedList)
                    {
                        if (row.Index != e.RowIndex)
                        {
                            row.Cells["_selectColumn"].Value = false;
                        }
                    }
                }

            }

            base.OnCellValueChanged(e);
        }

        protected override void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e)
        {
            _checkedList.RemoveWhere(x => !base.Rows.Contains(x));


            base.OnRowsRemoved(e);

        }

        protected override void OnDataSourceChanged(EventArgs e)
        {
            base.OnDataSourceChanged(e);

            if (this.DataSource is IDetailWithDynamicColumnsCollection)
            {
                var ds = (IDetailWithDynamicColumnsCollection)this.DataSource;
                //当数据源为包含动态列的数据源时,自动将表头改为双倍高度
                this.ColumnHeadersHeight = _rowHeight * 2;
            }
        }

        protected override void OnRowsAdded(DataGridViewRowsAddedEventArgs e)
        {

            base.OnRowsAdded(e);
        }

        protected override void Dispose(bool disposing)
        {
            _checkedList.Clear();
            base.Dispose(disposing);

        }
    }

    [ToolboxBitmap(typeof(DataGridViewDynamicColumn), "DataGridViewTextBoxColumn.bmp")]
    public class DataGridViewDynamicColumn : DataGridViewColumn
    {
        private DataGridViewDynamicColumnCell _cell = new DataGridViewDynamicColumnCell();
        private DataGridView _currentGrid = null;
        private object _currentDataSource = null;

        public DataGridViewDynamicColumn()
            : base(new DataGridViewDynamicColumnCell())
        {
            this.SortMode = DataGridViewColumnSortMode.NotSortable;
        }

        public string GroupName
        {
            set;
            get;
        }

        private static string[] _emptyList=new string[0];
        internal IList<object> Headers
        {
            get
            {
                var collection = (IDetailWithDynamicColumnsCollection)base.DataGridView.DataSource;

                if (collection.DynamicColumns.ContainsKey(GroupName.ToStringEx()))
                {
                    var lst = collection.DynamicColumns[GroupName].HeaderTextList.Select(x=>x.Key).ToArray();

                    Array.Sort(lst);

                    return lst;
                    //return collection.DynamicColumns[GroupName].HeaderTextList.Keys.ToArray();
                }
                else
                {
                    return _emptyList;
                }

                
            }
        }

        public override DataGridViewCell CellTemplate
        {
            get
            {
                return base.CellTemplate;
            }
            set
            {
                // Ensure that the cell used for the template is a CalendarCell.
                if (value != null &&
                    !value.GetType().IsAssignableFrom(typeof(DataGridViewDynamicColumnCell)))
                {
                    throw new InvalidCastException("Must be a DynamicColumnCell");
                }
                base.CellTemplate = (DataGridViewDynamicColumnCell)value;
            }
        }

        protected override void OnDataGridViewChanged()
        {
            base.OnDataGridViewChanged();

            if (_currentGrid != null)
            {
                _currentGrid.ColumnWidthChanged -= dataGridView_ColumnWidthChanged;
                _currentGrid.Scroll -= dataGridView_Scroll;
                _currentGrid.CellPainting -= dataGridView_CellPainting;
                _currentGrid.DataSourceChanged -= DataGridView_DataSourceChanged;

            }

            if (this.DataGridView != null)
            {
                this.DataGridView.ColumnWidthChanged += dataGridView_ColumnWidthChanged;
                this.DataGridView.Scroll += dataGridView_Scroll;
                this.DataGridView.CellPainting += dataGridView_CellPainting;
                this.DataGridView.DataSourceChanged += DataGridView_DataSourceChanged;


            }

            _currentGrid = this.DataGridView;

        }

        void DataGridView_DataSourceChanged(object sender, EventArgs e)
        {
            if (_currentDataSource != null && _currentDataSource is IDetailWithDynamicColumnsCollection)
            {

                var ds = (IDetailWithDynamicColumnsCollection)_currentGrid.DataSource;

                ds.DynamicColumnChanged -= ds_DynamicColumnChanged;
                ds.DynamicColumnValueChanged -= ds_DynamicColumnValueChanged;

            }

            if (this.DataGridView.DataSource != null && this.DataGridView.DataSource is IDetailWithDynamicColumnsCollection)
            {
                var ds = (IDetailWithDynamicColumnsCollection)this.DataGridView.DataSource;

                ds.DynamicColumnChanged += ds_DynamicColumnChanged;
                ds.DynamicColumnValueChanged += ds_DynamicColumnValueChanged;
            }

            _currentDataSource = this.DataGridView.DataSource;
        }

        private void ds_DynamicColumnValueChanged(object sender, DynamicColumnValueChangedEventArgs e)
        {
            //if (_currentGrid.DataSource!=null && !string.IsNullOrWhiteSpace(this.DataPropertyName))
            //{
            //    _currentGrid.BindingContext[_currentGrid.DataSource,this.DataPropertyName].EndCurrentEdit();
            //}
        }

        private void ds_DynamicColumnChanged(object sender, DynamicColumnChangedEventArgs<DynamicColumn> e)
        {
            //if (_currentGrid.DataSource != null && !string.IsNullOrWhiteSpace(this.DataPropertyName))
            //{
            //    _currentGrid.BindingContext[_currentGrid.DataSource, this.DataPropertyName].EndCurrentEdit();
            //}

            if (e.Action == DynamicColumnChangedAction.RefreshChildColumn)
            {
                _currentGrid.InvalidateColumn(this.DisplayIndex);
            }

        }

        private void dataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
        {
            var target = e.Column.DataGridView;

            target.Invalidate(target.DisplayRectangle);
        }

        private void dataGridView_Scroll(object sender, ScrollEventArgs e)
        {
            _currentGrid.Invalidate(_currentGrid.DisplayRectangle);
        }

        private void dataGridView_Paint(object sender, PaintEventArgs e)
        {

        }

        private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.RowIndex == -1 && e.ColumnIndex == this.DisplayIndex)
            {
                var r2 = e.CellBounds;
                r2.Y += e.CellBounds.Height / 2;
                r2.Height = e.CellBounds.Height / 2;
                e.PaintBackground(r2, true);
                //e.PaintContent(r2);
                drawMutilHeader(e);
                e.Handled = true;
            }
        }

        private void drawMutilHeader(DataGridViewCellPaintingEventArgs e)
        {
            var target = this.DataGridView;

            if (!target.Columns.Contains(this))
            {
                target.Paint -= dataGridView_Paint;
                return;
            }

            var cellStyle = target.ColumnHeadersDefaultCellStyle;

            var r1 = new Rectangle();
            var tempCell = target.GetCellDisplayRectangle(this.DisplayIndex, -1, false);

            r1.X += (tempCell.X+1);
            r1.Y += tempCell.Y;
            r1.Height = tempCell.Height;
            r1.Width = tempCell.Width;

            using (var pen = new Pen(new SolidBrush(target.GridColor), 1))
            {
                var borderRang = new Rectangle();
                borderRang.X = tempCell.X;
                borderRang.Y = tempCell.Y;
                borderRang.Width = tempCell.Width - 1;
                borderRang.Height = tempCell.Height - 1;

                e.Graphics.DrawRectangle(pen, borderRang);
            }

            r1.Height = tempCell.Height / 2;

            using (var pen = new Pen(cellStyle.ForeColor, 1.2f))
            {
                var sf = StyleChange(cellStyle.Alignment);

                if (!string.IsNullOrWhiteSpace(this.HeaderText))
                {
                    //绘制总分组表头
                    e.Graphics.DrawString(this.HeaderText, cellStyle.Font, pen.Brush, r1, sf);
                }

                pen.Width = 1;

                //绘制总分组表头与动态列之间的分界线
                e.Graphics.DrawLine(pen, r1.X, r1.Y + r1.Height + 1, r1.X + r1.Width-2, r1.Y + r1.Height + 1);

                r1.Y = r1.Y + r1.Height + 2;

                var innerCellWidth = 0f;

                if (this.Headers.Count > 1)
                {
                    innerCellWidth = (r1.Width - this.Headers.Count - 2f) / this.Headers.Count;

                    for (int i = 0; i < this.Headers.Count; i++)
                    {
                        var header = this.Headers[i];

                        var currentX = (innerCellWidth + 1) * i + r1.X;

                        var range = new RectangleF(currentX, r1.Y, innerCellWidth, r1.Height);
                        e.Graphics.DrawString(header.ToStringEx(), cellStyle.Font, pen.Brush,range, sf);
                        
                        if (i>0)
                        {
                            e.Graphics.DrawLine(pen, innerCellWidth * i + r1.X + 1, r1.Y, innerCellWidth * i + r1.X + 1, r1.Height + r1.Y - 1);
                        }
                    }
                }
                else if(this.Headers.Count>0)
                {
                    if (string.IsNullOrWhiteSpace(this.Headers[0].ToStringEx()))
                    {
                        e.Graphics.DrawString(this.Headers[0].ToString(), cellStyle.Font, pen.Brush, r1, sf);
                    }
                }
            }

        }

        private StringFormat StyleChange(DataGridViewContentAlignment style)
        {
            var sf = new StringFormat();

            switch (style)
            {
                case DataGridViewContentAlignment.BottomRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case DataGridViewContentAlignment.BottomLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case DataGridViewContentAlignment.BottomCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case DataGridViewContentAlignment.MiddleCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case DataGridViewContentAlignment.MiddleLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case DataGridViewContentAlignment.MiddleRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case DataGridViewContentAlignment.TopCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case DataGridViewContentAlignment.TopLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case DataGridViewContentAlignment.TopRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                default:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
            }

            return sf;
        }

    }


    public class DataGridViewDynamicColumnCell : DataGridViewCell
    {
        public DataGridViewDynamicColumnCell()
            : base()
        {

        }

        public override Type ValueType
        {
            get
            {
                return typeof(DynamicColumn);
            }
        }

        public override Type EditType
        {
            get
            {
                return typeof(DataGridViewDynamicColumnEditingControl);
            }
        }

        public override object DefaultNewRowValue
        {
            get
            {

                return new DynamicColumn() { };
            }
        }

        public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
        {
            DataGridViewDynamicColumnEditingControl ctl = DataGridView.EditingControl as DataGridViewDynamicColumnEditingControl;
            if (!(ctl is DataGridViewDynamicColumnEditingControl))
            {
                return;
            }

            ctl.Width = this.OwningColumn.Width;
            ctl.Height = this.DataGridView.Rows[rowIndex].Height;
            ctl.Value = (DynamicColumn)initialFormattedValue;
            base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);


        }

        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {

            //背景色
            Color clr_background = (cellState & DataGridViewElementStates.Selected) !=
                                   DataGridViewElementStates.Selected
                                       ? cellStyle.BackColor
                                       : cellStyle.SelectionBackColor;



            using (Brush bru = new SolidBrush(clr_background))
            {
                graphics.FillRectangle(bru, cellBounds);
            }

            //边框
            if ((paintParts & DataGridViewPaintParts.Border) != 0)
            {
                PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle);
            }

            if (value is DBNull || value == null || !(value is DynamicColumn))
            {
                return;
            }

            var dynamicColumn = (DynamicColumn)value;

            if (dynamicColumn.Collection == null)
            {
                return;
            }

            cellBounds.X += 1;

            var t = dynamicColumn.Collection.DynamicColumns[dynamicColumn.GroupName];

            var sf = StyleChange(cellStyle.Alignment);

            if (t.HeaderTextList.Count > 1)
            {
                float innerCellWidth = (cellBounds.Width - t.HeaderTextList.Count - 2f) / t.HeaderTextList.Count;

                using (var stringBrush = new SolidBrush((cellState & DataGridViewElementStates.Selected) != DataGridViewElementStates.Selected
                                                                                       ? cellStyle.ForeColor
                                                                                       : cellStyle.SelectionForeColor))
                {
                    int i = 0;
                    foreach (var columnConfig in t.HeaderTextList)
                    {
                        var currentX = (innerCellWidth + 1) * i + cellBounds.X;

                        if (dynamicColumn.ContainsKey(columnConfig.Key))
                        {


                            var range = new RectangleF(currentX, cellBounds.Y, innerCellWidth, cellBounds.Height);
                            graphics.DrawString(dynamicColumn[columnConfig.Key].ToString(), cellStyle.Font, stringBrush,
                                                range, sf);
                        }

                        i += 1;
                    }
                }

                using (var pen = new Pen(Color.Black, 1))
                {
                    //画出纵向的分割线
                    for (int i = 1; i < t.HeaderTextList.Count; i++)
                    {
                        graphics.DrawLine(pen, innerCellWidth * i + cellBounds.X + 1, cellBounds.Y, innerCellWidth * i + cellBounds.X + 1, cellBounds.Height + cellBounds.Y - 1);
                    }
                }
            }
            else if (t.HeaderTextList.Count == 1)
            {
                using (var stringBrush = new SolidBrush(cellStyle.ForeColor))
                {
                    var str = dynamicColumn.First();

                    if (dynamicColumn.ContainsKey(str.Key))
                    {
                        graphics.DrawString(dynamicColumn[str.Key].ToString(), cellStyle.Font, stringBrush,
                                            cellBounds, sf);
                    }
                }
            }
            //base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        }

        protected override void OnEnter(int rowIndex, bool throughMouseClick)
        {
            base.OnEnter(rowIndex, throughMouseClick);

            if (!this.OwningColumn.ReadOnly)
            {
                this.DataGridView.BeginEdit(true);
            }

        }

        private StringFormat StyleChange(DataGridViewContentAlignment style)
        {
            var sf = new StringFormat();

            switch (style)
            {
                case DataGridViewContentAlignment.BottomRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case DataGridViewContentAlignment.BottomLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case DataGridViewContentAlignment.BottomCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Far;
                    break;
                case DataGridViewContentAlignment.MiddleCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case DataGridViewContentAlignment.MiddleLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case DataGridViewContentAlignment.MiddleRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case DataGridViewContentAlignment.TopCenter:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case DataGridViewContentAlignment.TopLeft:
                    sf.Alignment = StringAlignment.Near;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case DataGridViewContentAlignment.TopRight:
                    sf.Alignment = StringAlignment.Far;
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                default:
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;
                    break;
            }

            return sf;
        }
    }

    public class DataGridViewDynamicColumnEditingControl : DataGridViewDynamicColumnTextBox, IDataGridViewEditingControl
    {
        public DataGridViewDynamicColumnEditingControl()
            : base()
        {

        }

        #region Implementation of IDataGridViewEditingControl

        public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
        {
            relayoutTextBox();

            for (int i = 0; i < lstTextbox.Count; i++)
            {
                var textbox = lstTextbox[i];

                textbox.ForeColor = dataGridViewCellStyle.ForeColor;
                textbox.BackColor = dataGridViewCellStyle.BackColor;
                textbox.Font = dataGridViewCellStyle.Font;
            }
        }

        public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
        {
            switch (keyData & Keys.KeyCode)
            {
                case Keys.Left:
                case Keys.Up:
                case Keys.Down:
                case Keys.Right:
                case Keys.Home:
                case Keys.End:
                case Keys.Tab:
                    return true;
                default:
                    return false;
            }
        }

        public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
        {
            return base.Value;
        }

        public void PrepareEditingControlForEdit(bool selectAll)
        {

        }

        private DataGridView _editingControlDataGridView;
        public DataGridView EditingControlDataGridView
        {
            get { return _editingControlDataGridView; }
            set
            {
                _editingControlDataGridView = value;
            }
        }


        public object EditingControlFormattedValue
        {
            get
            {
                return this.Value;
            }
            set
            {
                //_value =(DynamicColumn) value;
                this.Value = (DynamicColumn)value;
            }
        }

        public int EditingControlRowIndex { get; set; }
        public bool EditingControlValueChanged
        {
            get { return this.IsChanged; }
            set { this.IsChanged = true; }
        }
        public Cursor EditingPanelCursor { get { return base.Cursor; } }
        public bool RepositionEditingControlOnValueChange { get { return this.IsChanged; } }

        #endregion
    }

    public class DataGridViewDynamicColumnTextBox : Control
    {
        protected List<TextBox> lstTextbox = new List<TextBox>();
        private DynamicColumn _value = null;

        public DataGridViewDynamicColumnTextBox()
        {

        }

        public bool IsChanged { set; get; }

        public DynamicColumn Value
        {
            get { return _value; }
            set
            {
                if (_value != value)
                {
                    _value = value;
                    relayoutTextBox();
                }
            }
        }

        protected void relayoutTextBox()
        {
            int j = 0;

            lstTextbox.ForEach(x => x.Visible = false);

            var headers = _value.Collection.DynamicColumns[this.Value.GroupName];

            if (headers.HeaderTextList.Count <= 0)
            {
                return;
            }

            foreach (var column in headers.HeaderTextList)
            {
                TextBox textbox = null;

                if (j < lstTextbox.Count)
                {
                    textbox = lstTextbox[j];
                }
                else
                {
                    textbox = new TextBox();
                    textbox.Multiline = false;
                    textbox.BorderStyle = BorderStyle.FixedSingle;
                    textbox.BorderStyle = BorderStyle.FixedSingle;
                    textbox.Enter += textbox_Enter;
                    lstTextbox.Add(textbox);
                }

                textbox.TextChanged -= textbox_TextChanged;
                textbox.KeyDown -= textbox_KeyDown;

                textbox.Tag = column.Key;

                if (_value.ContainsKey(column.Key))
                {
                    textbox.Text = _value[column.Key].ToStringEx();
                }
                else
                {
                    textbox.Text = "";
                }

                textbox.Visible = true;
                this.Controls.Add(textbox);

                textbox.TextChanged += textbox_TextChanged;
                textbox.KeyDown += textbox_KeyDown;

                j += 1;
            }

            for (int i = 0; i < lstTextbox.Count; i++)
            {
                var textbox = lstTextbox[i];

                textbox.Width = this.Width / lstTextbox.Count;
                textbox.Height = this.Height + 1;
                textbox.Left = i * textbox.Width;
                textbox.Top = 0;
            }

            lstTextbox[0].Focus();

        }

        private void textbox_Enter(object sender, EventArgs e)
        {
            var txt = (TextBox)sender;

            txt.SelectionStart = 0;
            txt.SelectionLength = txt.Text.Length;
        }

        private void textbox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Tab)
            {
                var txt = (TextBox)sender;

                var index = lstTextbox.IndexOf(txt);

                if (index == lstTextbox.Count - 1)
                {
                    index = 0;
                }
                else
                {
                    index += 1;
                }

                lstTextbox[index].Focus();
            }
        }

        private void textbox_TextChanged(object sender, EventArgs e)
        {
            var txt = (TextBox)sender;

            this.Value[txt.Tag] = txt.Text;

            IsChanged = true;
        }


    }

    //[Designer(typeof(DesignerInherit))]
    //public class TableLayoutPanelEx:TableLayoutPanel
    //{}

    public class DesignerInherit : ControlDesigner
    {
        protected override InheritanceAttribute InheritanceAttribute
        {
            get
            {
                if (base.InheritanceAttribute == InheritanceAttribute.InheritedReadOnly)
                {
                    return InheritanceAttribute.Inherited;
                }
                else
                {
                    return base.InheritanceAttribute;
                }
            }
        }
    }
}
